const { AsyncSeriesHook, AsyncParallelHook, SyncHook } = require('tapable');

function TestSeries() {
  const hook = new AsyncSeriesHook(['name']);

  hook.tapAsync('01', (name, callback) => {
    setTimeout(() => {
      console.log('01 receive:', name, Date.now() - name);
      callback(); // 必须执行callback，才会进入02回调
    }, 80);
  });
  hook.tapAsync('02', (name, callback) => {
    setTimeout(() => {
      console.log('02 receive:', name, Date.now() - name);
      callback('02020202'); // 一旦报错，后续的03将不会执行
    });
  });
  hook.tapAsync('03', (name, callback) => {
    setTimeout(() => {
      console.log('03 receive:', name, Date.now() - name);
      callback();
    }, 40);
  });

  hook.callAsync('' + Date.now(), (err) => {
    if (err) {
      console.log('[ERROR]', err, Date.now());
    }
    console.log('over');
  });
}

/**
 * 所有的回调都会被执行，只有最先的报错 错误会被callback调用。所有的回调都没有报错，call内部才会done
 */
function TestParallel() {
  const hook = new AsyncParallelHook(['name']);

  hook.tapAsync('01', (name, callback) => {
    setTimeout(() => {
      console.log('01 receive:', name, Date.now() - name);
      callback('111111111111111111');
    }, 80);
  });
  hook.tapAsync('02', (name, callback) => {
    setTimeout(() => {
      console.log('02 receive:', name, Date.now() - name);
      callback();
    });
  });
  hook.tapAsync('03', (name, callback) => {
    setTimeout(() => {
      console.log('03 receive:', name, Date.now() - name);
      callback('0033333333');
    }, 40);
  });

  hook.callAsync('' + Date.now(), (err) => {
    if (err) {
      console.log('[ERROR]', err, Date.now());
    }
    console.log('over');
  });
}

function TestSyncCallAsync() {
  const hook = new SyncHook(['name']);
  hook.tap('1', console.log);

  console.log('before call');
  hook.callAsync('Jim', (err) => {
    console.log('In call-- after taps');
  });
  console.log('after call');
}
// TestSeries();
// TestParallel();
TestSyncCallAsync();

// Hook, AsyncHook 是个两个生成调用过程的核心类，不可new示例，可以理解为当前涉及的都是入口类。
// AsyncSeriesBailHook, AsyncSeriesLoopHook, AsyncSeriesWaterfallHook  这3个和同步钩子作用一样，无非就是支持异步而已
// AsyncParallelBailHook  由于是并行 所有回调都会被执行，但只有最先产生的返回值 会作为call的返回结果，其他回调的结果会被弃用
// 任何回调函数执行报错，如果不处理的话，错误都会抛给call。(这一点和watcher模式类似，但watcher模式可以用try-catch包装每个listener)
